home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Language/OS - Multiplatform Resource Library
/
LANGUAGE OS.iso
/
cpp_libs
/
tools
/
cie.lha
/
cie
/
hier-mode.el
< prev
next >
Wrap
Lisp/Scheme
|
1993-06-21
|
11KB
|
354 lines
;;; hier-mode.el
;;; Hierarchy mode (for hierarchies output by hier++)
;;; See the docstring for defun hier-mode for a description.
;;; Copyright (C) 1993, Intellection Inc.
;;;
;;; Author: Brian M Kennedy (kennedy@intellection.com)
;;;
;;; This program is free software; you can redistribute it and/or modify
;;; it under the terms of the GNU General Public License as published by
;;; the Free Software Foundation; either version 1, or (at your option)
;;; any later version.
;;;
;;; This program is distributed in the hope that it will be useful,
;;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
;;; GNU General Public License for more details.
;;;
;;; A copy of the GNU General Public License can be obtained from the
;;; Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
;;; 92/08 Brian M Kennedy Added direct access commands; added sort to member list
;;; 92/06 Brian M Kennedy Original
;;; (using other GNU Emacs modes as a template)
;;; Ideally, this mode should be rewritten based on outline.el, by simply setting
;;; a few of outline.el's variables. That would provide additional functionality
;;; such as hide/show. But to do it right, you should modify the other functions
;;; in this file to auto-show things being searched for (otherwise, hiding would
;;; be more a hindrance than a help).
(provide 'hier-mode)
(autoload 'visit-tags-table-buffer "tags")
(autoload 'prompt-for-tag "tags")
(defvar hier-mode-syntax-table nil
"Syntax table used while in hier mode.")
(if hier-mode-syntax-table
()
(setq hier-mode-syntax-table (make-syntax-table))
)
(defvar hier-mode-abbrev-table nil
"Abbrev table used while in bib mode.")
(define-abbrev-table 'hier-mode-abbrev-table ())
(defvar hier-mode-map nil "")
(if hier-mode-map
()
(setq hier-mode-map (make-sparse-keymap))
(define-key hier-mode-map "\M-h" 'hier-find)
(define-key hier-mode-map "\M-g" 'hier-find-again)
(define-key hier-mode-map "\M-m" 'hier-show-members)
(define-key hier-mode-map "\M-p" 'hier-previous-element)
(define-key hier-mode-map "\M-n" 'hier-next-element)
(define-key hier-mode-map "\M-u" 'hier-upto-parent)
)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(defun hier-mode ()
"Major mode for viewing class hierarchy files output by hier++.
The file is formatted like this:
* class_a
* child_b :class_a
* child_c :class_a :class_f
* grandchild_d :child_c
* grandchild_e :child_c
* class_f
* child_c :class_a :class_f
* grandchild_d :child_c
* grandchild_e :child_c
* child_g :class_f
Classes child_b and child_c are derived from class_a; classes child_c and
child_g are derived from class_f; classes grandchild_d and grandchild_e are
both derived from child_c. Note that each class (and all of its children)
will appear in the file once under each parent.
Defined keys:
M-p moves to the previous sibling
M-n moves to the next sibling
M-u moves up to the parent
M-h finds the first occurrence of the hierarchy element for a class
(similar to M-. in behavior)
M-g finds the next occurrence (like M-,) in the case of multiple-inheritance.
M-m brings up a new window with a listing of all the members (both direct and
inherited) of that hierarchy entry. It does this via tags, so you must
have tags set up in Emacs. It will also only work properly if the tags
file was generated by etags++ (companion to hier++)."
(interactive)
(kill-all-local-variables)
(use-local-map hier-mode-map)
(setq mode-name "Hierarchy")
(setq major-mode 'hier-mode)
(setq local-abbrev-table hier-mode-abbrev-table)
(set-syntax-table hier-mode-syntax-table)
;(run-hooks 'hier-mode-hook)
)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Find hierarchy elements
;; Return a default name to search for, based on the text at point.
(defun hier-find-default ()
(save-excursion
(while (looking-at "\\sw\\|\\s_")
(forward-char 1))
(if (re-search-backward "\\sw\\|\\s_" nil t)
(progn (forward-char 1)
(buffer-substring (point)
(progn (forward-sexp -1)
(while (looking-at "\\s'")
(forward-char 1))
(point))))
nil)))
(defun hier-find-element (string)
(let* ((default (hier-find-default))
(spec (read-string
(if default
(format "%s(default %s) " string default)
string))))
(list (if (equal spec "")
default
spec))))
(defvar hier-last-find-element nil
"The last element searched for by hier-find.")
(defun hier-find (element)
(interactive (hier-find-element "Find element: "))
(setq hier-last-find-element (concat "* " element " "))
(goto-char (point-min))
(hier-find-again)
)
(defun hier-find-again ()
(interactive)
(if hier-last-find-element
(search-forward hier-last-find-element)))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Cursor movement through hierarchy
(defun hier-previous-element (ignore)
"Goto previous hierarchy element at this level or higher."
(interactive "p")
(back-to-indentation)
(let ((indent (current-indentation)))
(previous-line 1)
(while (< indent (current-indentation))
(previous-line 1) ))
(back-to-indentation) )
(defun hier-next-element (ignore)
"Goto next hierarchy element at this level or higher."
(interactive "p")
(back-to-indentation)
(let ((indent (current-indentation)))
(next-line 1)
(while (< indent (current-indentation))
(next-line 1) ))
(back-to-indentation) )
(defun hier-upto-parent (arg)
"Goto the parent hierarchy element."
(interactive "p")
(let ((indent (current-indentation)))
(if (> indent 0)
(while (<= indent (current-indentation))
(forward-line -1) )))
(back-to-indentation) )
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Find Class Members
(defun hier-regexp-list (&optional re-list)
(end-of-line)
(let ((eol (point)))
(back-to-indentation)
(forward-char 2)
(let ((re (concat "\C-a"
(buffer-substring (point) (progn (while (looking-at "\\sw\\|\\s_")
(forward-char 1))
(point) ))
"::")))
(setq re-list (cons re re-list))
(forward-word 1)
(while (<= (point) eol)
(forward-word -1)
(let ((start (point))
(end (progn (while (looking-at "\\sw\\|\\s_")
(forward-char 1))
(point) )) )
(save-excursion
(hier-find (buffer-substring start end))
(setq re-list (hier-regexp-list re-list)) ))
(forward-word 1) )
re-list)))
(defvar hier-members-column 30
"Column to line up member names in *Members List* buffer.")
(defun hier-members-apropos (name re-list &optional data-members-only-p)
"Display list of all tags in tag table that regexp matches."
(save-excursion
(with-output-to-temp-buffer "*Members List*"
(if data-members-only-p
(princ "== Data Members of Class ")
(princ "== All Members of Class "))
(prin1 name)
(princ " ==")
(terpri)
(visit-tags-table-buffer)
(while re-list
(goto-char 1)
(while (re-search-forward (car re-list) nil t)
(skip-chars-backward "^\C-a")
(princ (buffer-substring (point)
(progn (end-of-line)
(point))))
(terpri)
(forward-line 1) )
(setq re-list (cdr re-list)) ))
(set-buffer "*Members List*")
;; Remove Non-Data Members?
(if data-members-only-p
;; remove lines not ending in "_" or "=" (title line)
(progn (goto-char (point-max))
(while (not (bobp))
(forward-char -2)
(if (not (looking-at "[_=]"))
(progn (forward-char 2)
(delete-region (point) (progn (forward-line -1) (point))))
(forward-line -1)))))
;; Sort Buffer
(goto-line 2)
(sort-regexp-fields nil "^.*$" "::[^:\n]*$" (point) (point-max))
;; Remove Duplicate Entries
(goto-line 2)
(while (not (save-excursion (forward-line 1) (eobp)))
(if (string-equal (buffer-substring (point) (progn (forward-line 1) (point)))
(buffer-substring (point) (progn (forward-line 1) (point))))
(delete-region (point) (progn (forward-line -1) (point))) )
(forward-line -1) )
;; Line Up Colons
(goto-char (point-min))
(while (search-forward "::" nil t)
(let ((indent (- hier-members-column (current-column))))
(if (> indent 0)
(progn (beginning-of-line)
(indent-to-column indent) )))
(forward-line 1) )
))
(defun hier-show-members (&optional data-members-only-p)
"Show the members, both direct and inherited, of this hierarchy element."
(interactive)
(save-excursion
(back-to-indentation)
(forward-char 2)
(let ((name (buffer-substring (point) (progn (while (looking-at "\\sw\\|\\s_")
(forward-char 1))
(point) ))) )
(hier-members-apropos name (hier-regexp-list) data-members-only-p) )))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Auxiliary Functions
(defun hier-base-list ()
"Returns a list of the names of all the direct base classes on the current line."
(save-excursion
(end-of-line)
(let ((base-list nil)
(eol (point)))
(back-to-indentation)
(forward-char 2)
(while (looking-at "\\sw\\|\\s_")
(forward-char 1))
(forward-word 1)
(while (<= (point) eol)
(forward-word -1)
(setq base-list (cons (buffer-substring (point)
(progn (while (looking-at "\\sw\\|\\s_")
(forward-char 1))
(point) ))
base-list))
(forward-word 1) )
base-list) ) )
(defun hier-derived-list ()
"Returns a list of the names of all the directly derived classes
from the one on the current line."
(save-excursion
(let ((derived-list nil)
(indent (current-indentation)))
(next-line 1)
(back-to-indentation)
(while (< indent (current-indentation))
(forward-char 2)
(setq derived-list (cons (buffer-substring (point)
(progn (while (looking-at "\\sw\\|\\s_")
(forward-char 1))
(point) ))
derived-list))
(hier-next-element 1) )
derived-list) ) )
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; External Functions
(defvar hier-file-name nil
"The filename in which to find the class hierarchy generated by hier++.")
(defun prompt-for-hier-file-name ()
"Get hier-file-name from user."
(setq hier-file-name
(read-file-name "File containing class hierarchy [typically CLASS.hier]: ")))
(defun class-hierarchy (class-name)
"Display the hierarchy for the given class. M-g for next occurrence."
(interactive (list (prompt-for-tag "Display hierarchy for class: ")))
(if (not hier-file-name)
(prompt-for-hier-file-name))
(find-file-other-window hier-file-name)
(hier-find class-name))
(defun class-members (class-name)
"Display all members for the given class."
(interactive (list (prompt-for-tag "Display all members for class: ")))
(save-excursion
(set-buffer (find-file-noselect hier-file-name))
(hier-find class-name)
(hier-show-members) ))
(defun class-data-members (class-name)
"Display the data members for the given class."
(interactive (list (prompt-for-tag "Display data members for class: ")))
(save-excursion
(set-buffer (find-file-noselect hier-file-name))
(hier-find class-name)
(hier-show-members t) ))